home *** CD-ROM | disk | FTP | other *** search
/ Crack It! / Crack It!.iso / CONTENT / JSTEST / JST300D.EXE / JSTEST.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-10-02  |  36.6 KB  |  1,017 lines

  1. {
  2.  ***
  3.  
  4.  JSTEST
  5.  Joystick Testing Utility Version 3.00
  6.  (C)Copyright Gerard Paul Java 1996
  7.  
  8.  Program Source File
  9.  
  10.  
  11.  This program is used to test up to two joysticks connected to the computer's
  12.  game control adapter.  It shows the computer's reponses to the joystick
  13.  the joystick's shaft action and button presses.  It can also be used to
  14.  tune the joystick for best performance.
  15.  
  16.  The game adapter should be adjusted for the computer's processing speed
  17.  in order for the joystick shaft to work properly.  This program will not
  18.  give accurate results if this requirement is not met.  The adapter should
  19.  therefore be suited to the computer in which it is installed.
  20.  
  21.  
  22.  This program is free software; you may distribute and/or modify it under
  23.  the terms of the GNU General Public License version 2 or (at your option)
  24.  any later version, as published by the Free Software Foundation.
  25.  
  26.  This program is distributed in the hope that it will be useful, but is
  27.  provided "AS IS", WITHOUT ANY WARRANTY, either expressed or implied,
  28.  including, but not limited to, warranty of MERCHANTABILITY or FITNESS FOR
  29.  A PARTICULAR PURPOSE.  See the GNU General Public License for details.
  30.  
  31.  You should have received a copy of the GNU General Public License along
  32.  with this program; if not, write to the Free Software Foundation, Inc.,
  33.  675 Mass Ave., Cambridge, MA 02139 USA.
  34.  
  35.  
  36.  PROGRAM INFORMATION
  37.  
  38.    Base language: Pascal
  39.    Compiler: Borland Turbo Pascal 5.5 or higher
  40.    Portability: DOS-based systems only
  41.                 Requires 100% IBM computer compatibility
  42.                 No consideration for non-compatible systems
  43.    Other information: 8086 assembly language routines included
  44.                       Assembled with the Turbo Assembler 2.0
  45.  
  46.  
  47.  REVISION HISTORY:
  48.  
  49.    Version 1.00 - 11/13/88    [QuickBASIC 3.00]      Not full-screen
  50.    Version 2.00 - 04/15/89    [QuickBASIC 4.00b+]    Center-box style
  51.                                MASM 5.0]
  52.    Version 2.50 - 04/15/90    [Turbo Pascal 5.0+     Center-box style
  53.                                Turbo Assembler 1.0]
  54.  
  55.  
  56.  ***
  57. }
  58.  
  59.  
  60. {$A+,B-,F-,I-,N-,R-,S-,V-}
  61. {$M 3072,0,1024}                          { 3K stack, 1K heap }
  62.  
  63. program JSTEST;
  64. uses
  65.   Dos,
  66.   Crt,
  67.   Joystick,
  68.   ScreenRt,
  69.   SysRt,
  70.   Instruc,
  71.   IntroRt,
  72.   MenuRt,
  73.   Error;
  74.  
  75. const                                       { untyped }
  76.   Selected = True;
  77.   NotSelected = False;
  78.  
  79.   StickA = False;             { Stick identification values. }
  80.   StickB = True;
  81.  
  82. type
  83.   Parameter1Type = string[2];
  84.  
  85.   ButtonStatType = string[4];        { Type of button status. }
  86.  
  87.   StickIDCharType = 'A'..'B';        { Characters to identify stick. }
  88.  
  89.   StickArgsAndOpnsType = object      { Object to hold joystick args and operations. }
  90.                            StickCoordArgX: byte;
  91.                            StickCoordArgY: byte;
  92.                            StickButtonDownArg1: byte;
  93.                            StickButtonDownArg2: byte;
  94.                            DetectID: word;
  95.                            CurrentStick: boolean;
  96.                            procedure Select(StickID: boolean);
  97.                            procedure IndicateAndSaveScreen;
  98.                            procedure SelectOtherStick;
  99.                            procedure ShowTrackingWindow;
  100.                            procedure ShowButtonWindow;
  101.                            procedure TuneStick;
  102.                          end;
  103.  
  104.  
  105. const                  { typed }
  106.   StickAParams: StickArgsAndOpnsType = (StickCoordArgX: 1;
  107.                                         StickCoordArgY: 2;
  108.                                         StickButtonDownArg1: 16;
  109.                                         StickButtonDownArg2: 32;
  110.                                         DetectID: DetectIDA;
  111.                                         CurrentStick: StickA);
  112.   StickBParams: StickArgsAndOpnsType = (StickCoordArgX: 4;
  113.                                         StickCoordArgY: 8;
  114.                                         StickButtonDownArg1: 64;
  115.                                         StickButtonDownArg2: 128;
  116.                                         DetectID: DetectIDB;
  117.                                         CurrentStick: StickB);
  118.  
  119. var
  120.   Parameter1: Parameter1Type;
  121.  
  122.   BackScreenBuff: ScreenBufferType;     { Save buffer for desktop. }
  123.   AuxScreenBuffer: ScreenBufferType;    { Save buffer for other screens. }
  124.  
  125.  
  126.  
  127. {---------- Internal procedure declarations ----------}
  128.  
  129.  
  130. {----------------------------------------------------------------------------
  131.  StickArgsAndOpnsType.Select: Sets the parameters in the parameter variable.
  132.  This variable is of an object type and sets the correct argument values to
  133.  the StickCoord and StickButtonDown functions.  StickID identifies either
  134.  stick A or stick B.
  135.  ----------------------------------------------------------------------------}
  136.  
  137. procedure StickArgsAndOpnsType.Select(StickID: boolean);
  138. begin { proc }
  139.   case StickID of
  140.    StickA: Self := StickAParams;            { StickA: set parameters for A. }
  141.    StickB: Self := StickBParams;         { Otherwise, set parameters for B. }
  142.   end; { case }
  143. end; { proc }
  144.  
  145.  
  146. {----------------------------------------------------------------------------
  147.  InitAndDoChecks: Displays an error box in case of incorrect syntax, and
  148.  sets the values of some variables depending on the video mode.
  149.  ----------------------------------------------------------------------------}
  150.  
  151. procedure InitAndDoChecks;
  152. begin { proc }
  153.   if (LastMode = 7) or (GetEnv('BW') = '1') then
  154.     begin { if }
  155.       NormOptKeyAttr := $7F;          { B/W and monochrome color scheme. }
  156.       SelectedOptKeyAttr := $F;
  157.       OptionNormTextAttr := $70;
  158.       OptionSelectedTextAttr := $7;
  159.       BoxAttr := $7F;
  160.       TextNormAttr := $70;
  161.       HelpLineTextAttr := $F;
  162.       ErrBoxAttr := $F;
  163.       ErrMsgAttr := $F;
  164.       TextHighAttr := $7F;
  165.     end { if }
  166.   else
  167.     begin { else }
  168.       NormOptKeyAttr := $1B;             { Color color scheme. }
  169.       SelectedOptKeyAttr := $B;
  170.       OptionNormTextAttr := $1E;
  171.       OptionSelectedTextAttr := $E;
  172.       BoxAttr := $13;
  173.       TextNormAttr := $1E;
  174.       HelpLineTextAttr := $71;
  175.       ErrBoxAttr := $4F;
  176.       ErrMsgAttr := $4E;
  177.       TextHighAttr := $1B;
  178.     end; { else }
  179.  
  180.   if Parameter1 <> Null then
  181.     ErrAbort('Invalid syntax; pass /? for command help');    { Else invalid parameters }
  182.  
  183.   SetTSSRValues;                 { Set values for screen save/restore. }
  184. end;  { proc }
  185.  
  186.  
  187. {---------------------------------------------------------------------------
  188.  IndicateAndSaveScreen: Indicates the stick to be (or being) tested in the
  189.  bottom line.  Saves the screen in BackScreenBuff.
  190.  ---------------------------------------------------------------------------}
  191.  
  192. procedure StickArgsAndOpnsType.IndicateAndSaveScreen;
  193. var
  194.   CharID: char;
  195.  
  196. begin { proc }
  197.   case CurrentStick of
  198.     StickA: CharID := 'A';
  199.     StickB: CharID := 'B';
  200.   end;  { case }
  201.  
  202.   TextAttr := TextHighAttr;Window(79,25,80,25);
  203.   Write(CharID);
  204.   SaveScreen(BackScreenBuff);
  205. end; { proc }
  206.  
  207.  
  208. {---------------------------------------------------------------------------
  209.  IndicateError: Displays an error box with a specified message and an
  210.  instruction to retry or abort.  It contains code to check for the R and
  211.  Esc keystrokes.
  212.  --------------------------------------------------------------------------}
  213.  
  214. procedure IndicateError(Msg1: ErrStrType;var Keystroke: char);
  215. begin
  216.   SaveScreen(AuxScreenBuffer);
  217.  
  218.   ErrBox(Msg1,
  219.          'Press R to retry, or Esc to cancel',Instruct);
  220.  
  221.   repeat
  222.     Keystroke := UpCase(GetKeyNoExt);
  223.   until (Keystroke = RetryKey) or (Keystroke = Esc);
  224.  
  225.   RestoreScreen(AuxScreenBuffer);
  226. end;
  227.  
  228.  
  229. {---------------------------------------------------------------------------
  230.  DisconnectError: Returns an error message if contact with the joystick
  231.  is lost.
  232.  ---------------------------------------------------------------------------}
  233.  
  234. procedure DisconnectError(var Response: char);
  235. begin
  236.   IndicateError('Error: unable to detect joystick',Response);
  237. end;
  238.  
  239.  
  240. {----------------------------------------------------------------------------
  241.  SelectOtherStick: Attempts to select the other joystick for testing if it
  242.  is found.  If not, a box appears indicating it's not there, and the switch
  243.  is aborted.
  244.  ---------------------------------------------------------------------------}
  245.  
  246. procedure StickArgsAndOpnsType.SelectOtherStick;
  247. var
  248.   TerminateLoop: boolean;
  249.   OtherStickPresent: boolean;
  250.   Response: char;
  251.  
  252. begin { proc }
  253.   Window(2,25,80,25);Write('Wait. . .');
  254.  
  255.   TerminateLoop := False;
  256.  
  257.   repeat
  258.     case CurrentStick of
  259.       StickA: OtherStickPresent := StickIsPresent(DetectIDB);
  260.       StickB: OtherStickPresent := StickIsPresent(DetectIDA);
  261.     end;  { case }
  262.  
  263.     if OtherStickPresent then
  264.       begin
  265.         RestoreScreen(BackScreenBuff);
  266.         Select(not CurrentStick);
  267.         IndicateAndSaveScreen;
  268.         TerminateLoop := True;
  269.       end  { if }
  270.     else
  271.       begin
  272.         IndicateError('Error detecting other joystick',Response);
  273.  
  274.         RestoreScreen(AuxScreenBuffer);
  275.  
  276.         if Response = Esc then
  277.           begin
  278.             RestoreScreen(BackScreenBuff);
  279.             TerminateLoop := True;
  280.           end; { if }
  281.       end;  { else }
  282.   until TerminateLoop;
  283. end; { proc }
  284.  
  285.  
  286. {---------------------------------------------------------------------------
  287.  ShowHelpScreen: The JSTEST help system.
  288.  ---------------------------------------------------------------------------}
  289.  
  290. procedure ShowHelpScreen(ScreenNo: byte);
  291. begin { proc }
  292.   Window(1,1,80,25);
  293.   SaveScreen(AuxScreenBuffer);                  { Save screen. }
  294.   JustSeeBox;
  295.   {$IFDEF Cyan}
  296.   TextAttr := $6F;
  297.   TextNormAttr := $6E;
  298.   TextHighAttr := $6F;
  299.   {$ELSE}
  300.   TextAttr := BoxAttr;
  301.   {$ENDIF}
  302.  
  303.   case ScreenNo of
  304.     0: begin
  305.          DrawBox(3,2,78,24,DoubleLine);
  306.          GotoXY(31,2);Write(' Help: Help System ');
  307.          Window(5,4,78,25);TextAttr := TextNormAttr;
  308.  
  309.          Writeln('At almost any point in this program, press F1 for help (help is not');
  310.          Writeln('available at error and instruction boxes).  Each help screen contains');
  311.          Writeln('instructions on what to do at the point from where it was invoked.');
  312.          Writeln;
  313.          Writeln('The help screens of the test windows also indicate the expected results');
  314.          Writeln('and/or the results that could mean one or more defects in the stick.  If');
  315.          Writeln('results don''t happen when they''re expected, or the defect symptoms do,');
  316.          Writeln('have the stick serviced.  (This program is for standard, 2-button joy-');
  317.          Writeln('sticks only.  The test procedures are not designed for other devices,');
  318.          Writeln('even though other devices that connect to the game adapter could be');
  319.          Writeln('erratically detected as joysticks.)  The game adapter and joystick(s)');
  320.          Writeln('must be IBM or compatible, and the adapter must be adjusted for or');
  321.          Writeln('expected to be used at the computer''s processing speed (adapters sup-');
  322.          Writeln('plied with the computer or a clone of it are already adjusted), and all');
  323.          Writeln('connections must be good for reliable results.');
  324.          Writeln;
  325.          Writeln('See the manual for details.');
  326.          Writeln;
  327.        end;  { 0 }
  328.     1: begin
  329.          DrawBox(3,6,78,19,DoubleLine);
  330.          GotoXY(30,6);Write(' Help: Menu Operation ');
  331.          Window(5,8,78,20);TextAttr := TextNormAttr;
  332.          Writeln('The Up and Down cursor keys move the selection bar up and down respect-');
  333.          Writeln('ively.  Home and End move it to the first and last options respectively.');
  334.          Writeln('Enter executes the option indicated by the bar.');
  335.          Writeln;
  336.          Writeln('Pressing the highlighted letters directly executes their corresponding');
  337.          Writeln('options.');
  338.          Writeln;
  339.          Writeln('The bottom line of the screen shows a description of the function of the');
  340.          Writeln('option indicated by the selection bar.');
  341.        end; { 1 }
  342.     2: begin
  343.          DrawBox(3,3,78,23,DoubleLine);
  344.          GotoXY(28,3);Write(' Help: Tracking Window ');
  345.          Window(5,5,78,24);
  346.          TextAttr := TextNormAttr;
  347.          Writeln('This test cannot be performed accurately if the game adapter is not adj-');
  348.          Writeln('usted for the computer''s processing speed.  This information assumes');
  349.          Writeln('this requirement is met.');
  350.          Writeln;
  351.          Writeln('The cursor should follow the movements of the joystick shaft, and be');
  352.          Writeln('outside the inner box box when the shaft is placed at extreme positions');
  353.          Writeln('Try tuning the joystick before this test.  Use this procedure only after');
  354.          Writeln('tuning, or if a tuning error occurs and you are told to test the shaft.');
  355.          Writeln('If an error occurs during tuning, or still the above cannot be met, the');
  356.          Writeln('stick is defective.  Without tuning, that the shaft might appear to work');
  357.          Writeln('normally even if it might really be defective.  Such a joystick will');
  358.          Writeln('cause a tuning error.  In this case, use this test to determine the');
  359.          Writeln('shaft problem.  Also, vibrations without shaft motion are possible.');
  360.          Writeln('Such vibrations are normal.');
  361.          Writeln;
  362.          Writeln('To return to the menu, press Esc, X, or Q.');
  363.        end; { 2 }
  364.     3: begin
  365.          DrawBox(3,5,78,21,DoubleLine);
  366.          GotoXY(30,5);Write(' Help: Button Testing ');
  367.          Window(5,7,78,24);TextAttr := TextNormAttr;
  368.          Writeln('The indicator should read Down when its button is pressed, Up if not.');
  369.          Writeln('Any other behavior indicates a malfunction.  The buttons should work');
  370.          Writeln('correctly regardless of the adapter''s speed setting.  If your joystick');
  371.          Writeln('has only one button, the Button 2 indicator must always read Up.');
  372.          Writeln;
  373.          Writeln('(Some joysticks'' buttons can behave in such manner that when they are');
  374.          Writeln('held down, they appear to be repeatedly pressed then released.  Should');
  375.          Writeln('this feature be active, the corresponding indicator should repeatedly');
  376.          Writeln('switch between Up and Down when a button is held down, Up otherwise.)');
  377.          Writeln;
  378.          Writeln('Press Esc, X, or Q to return to the menu.');
  379.          Writeln;
  380.        end; { 3 }
  381.     4: begin
  382.          DrawBox(3,3,78,23,DoubleLine);
  383.          GotoXY(29,3);Write(' Help: Tuning Window ');
  384.          Window(5,5,78,24);TextAttr := TextNormAttr;
  385.          Writeln('X and Y refer to the joystick''s horizontal and vertical coordinates');
  386.          Writeln('respectively.  The coordinates may indicate slight shaft vibration even');
  387.          Writeln('with no shaft motion along any axis or both axes.');
  388.          Writeln;
  389.          Writeln('This procedure is applicable only to joysticks with tuning controls.');
  390.          Writeln('Follow the instruction.  The value must increase or decrease depending');
  391.          Writeln('on its tuning control''s direction of movement when the shaft is kept');
  392.          Writeln('centered.  When the indicators show the stated values, press  a key to');
  393.          Writeln('test the joystick''s centering.  The stated numbers will change');
  394.          Writeln('accordingly, or if the joystick is tuned, a message box will appear,');
  395.          Writeln('indicating the joystick is now centered.  (Deviations of at most 7');
  396.          Writeln('from the stated values are tolerated because of the vibrations.)  If');
  397.          Writeln('a shaft error occurs, the joystick is malfunctioning.  Execute "Shaft');
  398.          Writeln('testing" from the menu to determine the problem.');
  399.          Writeln;
  400.          Writeln('Press Q, X, or Esc to return to the menu.');
  401.        end; { 4 }
  402.   end; { case }
  403.  
  404.   Writeln;
  405.   TextAttr := TextHighAttr;Write(ContMsg);         { Display message. }
  406.   WaitForKeypress;
  407.   RestoreScreen(AuxScreenBuffer);                  { Get rid of help. }
  408. end; { proc }
  409.  
  410.  
  411. {---------------------------------------------------------------------------
  412.  CommandHelp: Displays help information on the JSTEST command and startup
  413.  info.
  414.  ---------------------------------------------------------------------------}
  415.  
  416. procedure CommandHelp;
  417. begin
  418.   Assign(Output,'');Rewrite(Output);
  419.   Writeln('Help on the JSTEST command:');
  420.   Writeln;
  421.   Writeln('Command syntax: JSTEST [/?]');
  422.   Writeln;
  423.   Writeln('To bring up the main program screen, type JSTEST with no parameters.  The');
  424.   Writeln('program will determine the number of joysticks present (up to 2) and will');
  425.   Writeln('select the proper stick.  The program menu will not come up if no stick is');
  426.   Writeln('found at startup.  If both are present, the program will select joystick A.');
  427.   Writeln('(Some adapters have two game ports into which separate A and B joysticks can');
  428.   Writeln('be plugged.  No error is therefore reported for as long as at least one joy-');
  429.   Writeln('stick is detected.)  Detection errors mean problems with the joystick(s) if');
  430.   Writeln('it/they is/are attached well.  This program is for joysticks only.  Other');
  431.   Writeln('devices that connect to the game adapter could be erratically detected, but');
  432.   Writeln('the test procedures are not designed for these.');
  433.   Writeln;
  434.   Writeln('Set the value of the CGASNOWCHECK environment variable to 1 to suppress "snow"');
  435.   Writeln('on old CGAs.  Set the value of the BW environment variable to 1 to bring the');
  436.   Writeln('program up in black and white mode.  (From DOS, issue SET CGASNOWCHECK=1 and/');
  437.   Writeln('or SET BW=1.)');
  438.   Writeln;
  439.   Writeln('No parameters other than /? are accepted.');
  440.   Writeln;
  441.   Writeln('JSTEST Version 3.00: Copyright Gerard Paul Java 1996');
  442. end;  { proc }
  443.  
  444.  
  445. {---------------------------------------------------------------------------
  446.  ShowTrackingWindow: Opens a window containing a cursor to track the shaft's
  447.  movements.
  448.  ---------------------------------------------------------------------------}
  449.  
  450. procedure StickArgsAndOpnsType.ShowTrackingWindow;
  451. const
  452.   xMaxPos = 47;
  453.   yMaxPos = 19;
  454.  
  455. var
  456.   xRange: word;
  457.   yRange: word;
  458.  
  459.   xPos: byte;
  460.   yPos: byte;
  461.  
  462.   Keystroke: char;
  463.  
  464.   ExitTracking: boolean;
  465.  
  466. begin
  467.   Window(1,1,80,25);
  468.  
  469.   JustSeeBox;
  470.  
  471.   InstBox(13,16,'Center the joystick shaft',
  472.                 CancelOrContMsg);
  473.  
  474.   Beep(900,100);
  475.   Keystroke := GetKeyNoExt;
  476.  
  477.   RestoreScreen(BackScreenBuff);             { Saved earlier at menu. }
  478.  
  479.   if Keystroke <> Esc then
  480.     begin
  481.       { For the range computation and plotting, the coordinates are
  482.         increased by 1 to increase the minimum value to 1.  This will
  483.         avoid problems with range computation with zero coordinates.
  484.         But because minimum coordinates for both axes are now 1, to
  485.         plot more accurately, the coordinates to be plotted must also
  486.         be increased by 1. }
  487.  
  488.       XRange := (StickCoord(StickCoordArgX)+1)*2;     { Determine ranges. }
  489.       YRange := (StickCoord(StickCoordArgY)+1)*2;
  490.  
  491.       Window(1,1,80,25);
  492.  
  493.       TextAttr := BoxAttr;DrawBox(4,3,77,23,DoubleLine);
  494.       DivideBox(52,3,23);
  495.       GotoXY(24,3);Write(' Tracking ');
  496.       ShowInstTitle(57,3);
  497.       TextAttr := TextNormAttr;
  498.       Window(54,5,76,24);
  499.       Writeln('See whether the');
  500.       Writeln('cursor correctly');
  501.       Writeln('follows shaft move-');
  502.       Writeln('ments.  The cursor');
  503.       Writeln('must be outside the');
  504.       Writeln('inner box when the');
  505.       Writeln('shaft is placed at');
  506.       Writeln('extreme positions.');
  507.       Writeln('Use this procedure');
  508.       Writeln('only after tuning');
  509.       Writeln('the shaft or if an');
  510.       Writeln('error occurs during');
  511.       Writeln('tuning.  If the above');
  512.       Writeln('conditions do not');
  513.       Writeln('occur, or a tuning');
  514.       Writeln('error occurs, the');
  515.       Writeln('stick is bad.');
  516.  
  517.       Window(5,4,51,22);ClrScr;              { Make the cursor yellow. }
  518.       DrawBox(9,5,36,15,SingleLine);
  519.  
  520.       ExitTracking := False;
  521.  
  522.       SetCursor($000F);
  523.  
  524.       repeat
  525.         if StickIsPresent(DetectID) then
  526.           begin
  527.             xPos := Trunc(((StickCoord(StickCoordArgX)+1)/xRange)*46)+1;
  528.             yPos := Trunc(((StickCoord(StickCoordArgY)+1)/yRange)*18)+1;
  529.  
  530.             if xPos > xMaxPos then            { Ensure cursor stays in }
  531.               xPos := xMaxPos;                { tracking window. }
  532.  
  533.             if yPos > yMaxPos then
  534.               yPos := yMaxPos;
  535.  
  536.             GotoXY(xPos,yPos);
  537.  
  538.             if KeyPressed then
  539.               begin
  540.                 Keystroke := UpCase(ReadKey);
  541.  
  542.                 case Keystroke of
  543.                   ExtKey      : if ReadKey = F1 then
  544.                                   begin
  545.                                     SetCursor($FFFF);
  546.                                     ShowHelpScreen(2);
  547.                                     SetCursor($000F);
  548.                                   end;
  549.                   Esc,
  550.                   ExitKey,
  551.                   AltExitKey  : ExitTracking := True;
  552.                 end;  { case }
  553.               end;  { if KeyPressed }
  554.           end
  555.         else
  556.           begin
  557.             SetCursor($FFFF);
  558.             DisconnectError(Keystroke);
  559.             if Keystroke = Esc then
  560.               ExitTracking := True
  561.             else
  562.               begin
  563.                 Window(5,4,51,22);
  564.                 SetCursor($000F);
  565.               end;
  566.           end;
  567.       until ExitTracking;
  568.  
  569.       SetCursor($FFFF);
  570.       end;  { if not Esc }
  571. end;  { proc }
  572.  
  573.  
  574. {----------------------------------------------------------------------------
  575.  ShowButtonWindow: Displays a window showting statuses of the joystick
  576.  buttons.
  577.  ----------------------------------------------------------------------------}
  578.  
  579. procedure StickArgsAndOpnsType.ShowButtonWindow;
  580. var
  581.   Keystroke: char;
  582.   ExitTest: boolean;
  583.  
  584. {---------------------------------------------------------------------------
  585.  ButtonStat: Reports the statuses of the joystick buttons. Returns "Up  "
  586.  if indicated button is not pressed, "Down" otherwise.
  587.  ---------------------------------------------------------------------------}
  588.  
  589. function ButtonStat(TrigArg: byte): ButtonStatType;
  590. begin { ButtonStat }
  591.   if StickButtonDown(TrigArg) then
  592.     ButtonStat := 'Down'
  593.   else
  594.     ButtonStat := 'Up  ';
  595. end; { ButtonStat }
  596.  
  597. begin { proc }
  598.   TextAttr := BoxAttr;Window(1,1,80,25);DrawBox(8,8,73,17,DoubleLine);
  599.   DivideBox(30,8,17);
  600.  
  601.   GotoXY(10,8);Write(' Buttons'' Statuses ');
  602.   ShowInstTitle(45,8);
  603.  
  604.   TextAttr := TextNormAttr;
  605.  
  606.   Window(32,12,72,17);
  607.   Writeln('See whether the indicators correctly');      { Instruction. }
  608.   Writeln('reflect the buttons'' statuses.');           { This should be }
  609.                                                         { enough. }
  610.   Window(13,12,58,16);
  611.   Writeln('Button 1:');                    { Button indicators. }
  612.   Write('Button 2:');
  613.  
  614.   ExitTest := False;
  615.  
  616.   TextAttr := TextHighAttr;
  617.   repeat
  618.     if StickIsPresent(DetectID) then
  619.       begin
  620.         Window(23,12,67,19);
  621.         TextAttr := TextHighAttr;
  622.         Writeln(ButtonStat(StickButtonDownArg1));  { Display button statuses. }
  623.         Write(ButtonStat(StickButtonDownArg2));
  624.  
  625.         if KeyPressed then
  626.           begin
  627.             Keystroke := UpCase(ReadKey);
  628.  
  629.             case Keystroke of
  630.               ExtKey    : if ReadKey = F1 then
  631.                             ShowHelpScreen(3);
  632.               ExitKey,
  633.               AltExitKey,
  634.               Esc       : ExitTest := True;
  635.              end; { case }
  636.           end; { if KeyPressed }
  637.         end
  638.       else
  639.         begin
  640.           DisconnectError(Keystroke);
  641.           if Keystroke = Esc then
  642.             ExitTest := True;
  643.         end;
  644.   until ExitTest;
  645. end; { proc }
  646.  
  647.  
  648. {----------------------------------------------------------------------------
  649.  TuneStick: Instructs the user to adjust the joystick's tuning controls
  650.  according to its recommendation.
  651.  ---------------------------------------------------------------------------}
  652.  
  653. procedure StickArgsAndOpnsType.TuneStick;
  654. var
  655.   Keystroke: char;
  656.   ExitLoop: boolean;
  657.   Row: byte;
  658.   xMin,yMin: word;
  659.   xMax,yMax: word;
  660.   xCen,yCen: word;
  661.   xRec,yRec: word;
  662.  
  663. {--------------------------------------------------------------------------
  664.  GetMinMax: Prompts the user for appropriate shaft action and retrieves
  665.  the minimum and maximum diagonal coordinates.
  666.  --------------------------------------------------------------------------}
  667.  
  668. procedure GetMinMax(var xMin,yMin,xMax,yMax: word;var Keystroke: char);
  669. begin
  670.   SaveScreen(AuxScreenBuffer);
  671.   if Keystroke <> Esc then
  672.     begin
  673.  
  674.        InstBox(13,16,'Move the shaft to the upper left corner',
  675.                      CancelOrContMsg);
  676.  
  677.        Keystroke := GetKeyNoExt;
  678.        RestoreScreen(AuxScreenBuffer);
  679.  
  680.        if Keystroke <> Esc then
  681.          begin
  682.            xMin := StickCoord(StickCoordArgX);     { Get minimum coordinates. }
  683.            yMin := StickCoord(StickCoordArgY);
  684.  
  685.            InstBox(13,16,'Move the shaft to the lower right corner',
  686.                          CancelOrContMsg);
  687.  
  688.            Keystroke := GetKeyNoExt;
  689.            RestoreScreen(AuxScreenBuffer);
  690.  
  691.            if Keystroke <> Esc then
  692.              begin
  693.                xMax := StickCoord(StickCoordArgX);    { Get maximum coordinates. }
  694.                yMax := StickCoord(StickCoordArgY);
  695.              end;
  696.          end;
  697.     end;
  698. end;
  699.  
  700.  
  701. {--------------------------------------------------------------------------
  702.  TestCentering: Calculates the midpoint coordinates according to the min
  703.  and max coordinates passed as parameters.
  704.  --------------------------------------------------------------------------}
  705.  
  706. procedure TestCentering(var xMin,yMin,xMax,yMax,
  707.                             xRec,yRec: word);
  708. begin
  709.   xRec := (xMin+xMax) div 2;             { Calculate midpoint. }
  710.   yRec := (yMin+yMax) div 2;
  711. end;
  712.  
  713.  
  714. {--------------------------------------------------------------------------
  715.  TuneInstruc: Prints the the recommended values in the instruction section.
  716.  --------------------------------------------------------------------------}
  717.  
  718. procedure TuneInstruc(xRec,yRec: word);
  719. begin
  720.   Window(34,14,72,17);
  721.   TextAttr := TextNormAttr;
  722.   Writeln('  X=',xRec:5,'       Y=',yRec:5);
  723. end;
  724.  
  725. begin
  726.   SaveScreen(AuxScreenBuffer);
  727.   InstBox(13,16,'Make sure tuning controls are away from extreme positions',
  728.                 CancelOrContMsg);
  729.  
  730.   Keystroke := GetKeyNoExt;
  731.   RestoreScreen(AuxScreenBuffer);
  732.  
  733.   if Keystroke <> Esc then
  734.     begin
  735.       GetMinMax(xMin,yMin,xMax,yMax,Keystroke);
  736.  
  737.       if Keystroke <> Esc then
  738.         begin
  739.           TestCentering(xMin,yMin,xMax,yMax,xRec,yRec);
  740.  
  741.           TextAttr := BoxAttr;Window(1,1,80,25);DrawBox(8,8,73,17,DoubleLine);
  742.           DivideBox(30,8,17);
  743.  
  744.           GotoXY(13,8);Write(' Coordinates ');                  { Titles. }
  745.           ShowInstTitle(45,8);
  746.  
  747.           TextAttr := TextNormAttr;Window(32,10,72,17);
  748.           Writeln('Keep the shaft centered and adjust the');   { Instruction. }
  749.           Writeln('tuning controls to set the coordinates');   { This should be }
  750.           Writeln('to as close to these values as possible:');    { enough. }
  751.  
  752.           TuneInstruc(xRec,yRec);
  753.  
  754.           Window(16,12,26,15);
  755.           Writeln('X=');
  756.           Write('Y=');
  757.  
  758.           ExitLoop := False;
  759.  
  760.           repeat
  761.             if StickIsPresent(DetectID) then
  762.               begin
  763.                 TextAttr := TextHighAttr;
  764.                 Window(19,12,35,19);
  765.                 Writeln(StickCoord(StickCoordArgX):5);     { Show coordinates. }
  766.                 Write(StickCoord(StickCoordArgY):5);
  767.  
  768.                 if KeyPressed then
  769.                   begin
  770.                     Keystroke := UpCase(ReadKey);
  771.  
  772.                     case Keystroke of
  773.                       ExtKey: if ReadKey = F1 then
  774.                                 ShowHelpScreen(4);
  775.                       Esc,
  776.                       ExitKey,
  777.                       AltExitKey: ExitLoop := True;
  778.                     else
  779.                       begin
  780.                         SaveScreen(AuxScreenBuffer);
  781.  
  782.                         InstBox(12,15,'Center the shaft',
  783.                                       CancelOrContMsg);
  784.                         Keystroke := GetKeyNoExt;
  785.                         RestoreScreen(AuxScreenBuffer);
  786.  
  787.                         if Keystroke <> Esc then
  788.                           begin
  789.                             xCen := StickCoord(StickCoordArgX);
  790.                             yCen := StickCoord(StickCoordArgY);
  791.  
  792.                             GetMinMax(xMin,yMin,xMax,yMax,Keystroke);
  793.  
  794.                             if Keystroke <> Esc then
  795.                               if (xMin >= xCen) or (xMax <= xCen) or
  796.                                  (yMin >= yCen) or (yMax <= yCen) then
  797.                                 begin
  798.                                    TextAttr := ErrBoxAttr;
  799.                                    Window(1,1,80,25);
  800.                                    DrawBox(16,5,65,20,DoubleLine);Window(18,7,71,21);
  801.                                    TextAttr := ErrMsgAttr;
  802.                                    Writeln('Error: Shaft malfunction.  Stick cannot be');
  803.                                    Writeln('tuned.');
  804.                                    Writeln;
  805.                                    Writeln('The joystick is not properly sending the');
  806.                                    Writeln('signals to the computer.  The coordinates');
  807.                                    Writeln('therefore do not correspond to the actual');
  808.                                    Writeln('shaft position.');
  809.                                    Writeln;
  810.                                    Writeln('Ensure the joystick is properly connected,');
  811.                                    Writeln('then execute "Shaft testing" to determine');
  812.                                    Writeln('the problem.');
  813.                                    Writeln;
  814.                                    TextAttr := ErrBoxAttr;
  815.                                    Writeln('Press a key to return to the main menu');
  816.                                    ErrSound;
  817.                                    WaitForKeyPress;
  818.                                    ExitLoop := True;
  819.                                 end
  820.                               else
  821.                                 begin
  822.                                   TestCentering(xMin,yMin,xMax,yMax,xRec,yRec);
  823.  
  824.                                   if (xRec >= xCen-7) and (xRec <= xCen+7) and
  825.                                      (yRec >= yCen-7) and (yRec <= yCen+7) then
  826.                                     begin
  827.                                       InstBox(12,15,'The joystick is tuned',
  828.                                                     'Press a key to return to the main menu');
  829.  
  830.                                       WaitForKeyPress;
  831.                                       ExitLoop := True;
  832.                                     end
  833.                                   else
  834.                                     TuneInstruc(xRec,yRec);
  835.                                 end;
  836.                           end
  837.                       end;
  838.                     end;  { case }
  839.                   end;  { if KeyPressed }
  840.               end
  841.             else
  842.               begin
  843.                 DisconnectError(Keystroke);
  844.                 if Keystroke = Esc then
  845.                   ExitLoop := True;
  846.               end;
  847.           until ExitLoop;
  848.         end;
  849.     end;
  850. end;  { proc }
  851.  
  852.  
  853. {---------------------------------------------------------------------------
  854.  ProgInterface: Sets up the screen and waits for input. This procedure
  855.  contains the screen setup and the pre-test interface.
  856.  ---------------------------------------------------------------------------}
  857.  
  858. procedure ProgInterface;
  859. var
  860.   Postn: byte;
  861.   Keystroke: char;
  862.   Menu: MenuType;
  863.   HelpSignal: boolean;
  864.  
  865.   StickArgsAndOpns: StickArgsAndOpnsType;      { Arguments to the joystick
  866.                                                  functions. }
  867.   
  868. {---------------------------------------------------------------------------
  869.  SelectDefaultStick: Selects the first joystick it finds.  It sets the
  870.  parameter variable, but indication is done by the IntroScreen procedure,
  871.  since the screen has to be done first.  This is called so that if no
  872.  sticks are found, the main screen won't come up.
  873.  ---------------------------------------------------------------------------}
  874.  
  875. procedure SelectDefaultStick;
  876. var
  877.   Error: boolean;
  878.  
  879. begin
  880.   InitAndCheckGameSys(Error);   { Attempt to init and check for a joystick. }
  881.  
  882.   {$IFDEF NoStick}
  883.   if not Error then
  884.   {$ELSE}
  885.   if Error then                 { No sticks nor adapter present? }
  886.   {$ENDIF}
  887.     ErrAbort('Error: no joysticks detected')
  888.   else if StickIsPresent(DetectIDA) then      { How 'bout stick A? }
  889.     StickArgsAndOpns.Select(StickA)
  890.   else
  891.     StickArgsAndOpns.Select(StickB);          { Gotta be stick B. }
  892. end;  { proc }
  893.  
  894.  
  895. {--------------------------------------------------------------------------
  896.  IntroScreen: Draws the introductory box.  This box disappears when a key
  897.  other than F1 is pressed.  F1 brings up a screen showing information on
  898.  the built-in help system.
  899.  --------------------------------------------------------------------------}
  900.  
  901. procedure IntroScreen;
  902. var
  903.   Keystroke: char;
  904.   TerminateLoop: boolean;
  905.   Postn: byte;
  906.  
  907. begin
  908.   DrawDesktop;
  909.   TextAttr := TextNormAttr;GotoXY(2,1);Writeln('JSTEST Version 3.00');
  910.   SaveScreen(BackScreenBuff);
  911.  
  912.   DrawIntroBox;                      { DrawBox(13,8,68,15,DoubleLine) }
  913.  
  914.   TextAttr := TextNormAttr;
  915.   Writeln('JSTEST');
  916.   Writeln('Joystick Testing and Tuning Utility Version 3.00');
  917.   Writeln('(C)Copyright Gerard Paul Java 1996');
  918.   Writeln;
  919.   TextAttr := TextHighAttr;
  920.   Write('Press F1 for help on help, any other key to continue');
  921.  
  922.   TerminateLoop := False;
  923.  
  924.   repeat
  925.     Keystroke := UpCase(ReadKey);
  926.     if Keystroke = ExtKey then
  927.       begin
  928.         if ReadKey = F1 then
  929.           ShowHelpScreen(0)
  930.         else
  931.           TerminateLoop := True;
  932.       end
  933.     else
  934.       TerminateLoop := True;
  935.   until TerminateLoop;
  936.  
  937.   Window(1,1,80,25);
  938.   RestoreScreen(BackScreenBuff);
  939.  
  940.   GotoXY(2,25);Write('F1');
  941.   TextAttr := TextNormAttr;Write('-help');
  942.   GotoXY(58,25);Write(#179' Selected joystick:');
  943.   StickArgsAndOpns.IndicateAndSaveScreen;
  944. end; { proc }
  945.  
  946. begin { ProgInterface }
  947.   SelectDefaultStick;
  948.  
  949.   IntroScreen;                          { Startup screen. }
  950.  
  951.   Menu.Init;
  952.  
  953.   with Menu do
  954.     begin
  955.       AddItem('Select other ^joystick','Selects other joystick for testing');
  956.       AddItem('^Shaft testing','Shows responses to joystick movements');
  957.       AddItem('^Button testing','Brings up the button testing window');
  958.       AddItem('^Tune joystick','Brings up the joystick tuning window');
  959.       AddItem('E^xit program','Exits program');
  960.     end;
  961.  
  962.   Menu.SetScreenPos(25,8);
  963.  
  964.   Postn := 1;
  965.  
  966.   repeat
  967.     Menu.Show;
  968.  
  969.     repeat
  970.       Menu.Operate(Postn,HelpSignal);
  971.       if HelpSignal then
  972.         ShowHelpScreen(1);
  973.     until not HelpSignal;
  974.  
  975.     RestoreScreen(BackScreenBuff);
  976.  
  977.     case Postn of                  { Execute options according to row. }
  978.       1: StickArgsAndOpns.SelectOtherStick;  { saves screen }
  979.       2: StickArgsAndOpns.ShowTrackingWindow;
  980.       3: StickArgsAndOpns.ShowButtonWindow;
  981.       4: StickArgsAndOpns.TuneStick;
  982.     end; { case Postn }
  983.  
  984.     RestoreScreen(BackScreenBuff);
  985.   until (Postn = 5) or (Postn = 0);    { 5=last item, 0=Esc pressed. }
  986.  
  987.   Release(HeapOrg);                    { Free heap. }
  988. end; { proc }
  989.  
  990.  
  991. {---------------------------------------------------------------------------
  992.  JSTEST: This is the main program, consisting mainly of procedure calls.
  993.  ---------------------------------------------------------------------------}
  994.  
  995. begin { program }
  996.   Parameter1 := ParamStr(1);                      { Store parameter. }
  997.  
  998.   if Parameter1 = '/?' then                       { Command help parameter? }
  999.     CommandHelp                                   { Yes, show it. }
  1000.   else
  1001.     begin
  1002.       CheckBreak := BreakOff;                     { Don't wanna break it. }
  1003.  
  1004.       ScreenInit;
  1005.  
  1006.       if (GetEnv('CGASNOWCHECK') = '1') and (LastMode <> Mono) then
  1007.         CheckSnow := SnowCheckOn
  1008.       else
  1009.         CheckSnow := SnowCheckOff;
  1010.  
  1011.       InitAndDoChecks;                             { Do checks. }
  1012.       ProgInterface;                               { Setup screen and menu. }
  1013.  
  1014.       TerminateProg(0);                            { Terminate. }
  1015.     end; { else }
  1016. end.  { program }
  1017.